/**
 * 客服工作台 WebSocket 管理器
 * 基于 Socket.IO 实现实时通信
 */

import { io, type Socket } from "socket.io-client";
import { getToken } from "@/utils/auth";
import type { Message, MessageType } from "@/api/customer-service";

// WebSocket 事件类型定义
export interface SocketEvents {
  // 连接事件
  connected: (data: { status: string; message: string; user_id: number; user_type: string }) => void;

  // 聊天室事件
  room_joined: (data: { room_id: number; message: string }) => void;
  room_left: (data: { room_id: number; message: string }) => void;
  user_joined: (data: {
    room_id: number;
    user: { id: number; type: string; name: string };
    message: string;
  }) => void;

  // 消息事件
  new_message: (data: Message) => void;

  // 输入状态事件
  user_typing: (data: {
    room_id: number;
    user: { id: number; type: string; name: string };
    is_typing: boolean;
  }) => void;

  // 错误事件
  error: (data: { message: string }) => void;

  // 会话状态变更事件
  room_status_changed: (data: {
    room_id: number;
    status: string;
    changed_by: { id: number; type: string; name: string };
  }) => void;

  // 会话分配事件
  room_assigned: (data: { room_id: number; assigned_to: number; assigned_by: number }) => void;

  // 房间在线用户更新事件
  room_online_users_update: (data: {
    room_id: number;
    online_users: Array<{
      id: number;
      type: string;
      name: string;
      avatar?: string;
      is_online: boolean;
      online_status: string;
    }>;
    online_count?: number;
  }) => void;

  // 用户状态变化事件
  user_status_change: (data: {
    user: {
      id: number;
      type: string;
      name: string;
      avatar?: string;
      phone?: string;
      is_online: boolean;
      last_seen_at?: string;
      online_status: string;
    };
    is_online: boolean;
    timestamp: string;
    event_type: "user_online" | "user_offline";
  }) => void;
}

/**
 * 客服工作台 WebSocket 管理器类
 */
export class CustomerServiceSocket {
  private socket: Socket | null = null;
  private reconnectAttempts = 0;
  private maxReconnectAttempts = 5;
  private reconnectDelay = 3000;
  private eventHandlers: Map<string, Set<Function>> = new Map();

  /**
   * 连接到 WebSocket 服务器
   * @param url WebSocket 服务器地址
   */
  connect(url: string = "http://localhost:5050"): Promise<void> {
    return new Promise((resolve, reject) => {
      const token = getToken();
      if (!token) {
        reject(new Error("未找到认证令牌"));
        return;
      }

      // 创建 Socket.IO 连接
      this.socket = io(url, {
        auth: {
          token: token.accessToken || token
        },
        transports: ["websocket", "polling"],
        reconnection: true,
        reconnectionDelay: this.reconnectDelay,
        reconnectionAttempts: this.maxReconnectAttempts
      });

      // 连接成功
      this.socket.on("connect", () => {
        console.log("✅ WebSocket 连接成功");
        this.reconnectAttempts = 0;
      });

      // 认证成功
      this.socket.on("connected", data => {
        console.log("✅ WebSocket 认证成功:", data);
        this.emit("connected", data);
        resolve();
      });

      // 连接错误
      this.socket.on("connect_error", error => {
        console.error("❌ WebSocket 连接错误:", error.message);
        this.reconnectAttempts++;

        if (this.reconnectAttempts >= this.maxReconnectAttempts) {
          reject(new Error(`连接失败，已重试 ${this.maxReconnectAttempts} 次`));
        }
      });

      // 断开连接
      this.socket.on("disconnect", reason => {
        console.warn("⚠️ WebSocket 断开连接:", reason);
        this.emit("disconnect", { reason });
      });

      // 错误处理
      this.socket.on("error", data => {
        console.error("❌ WebSocket 错误:", data);
        this.emit("error", data);
      });

      // 注册所有业务事件监听器
      this.registerEventListeners();
    });
  }

  /**
   * 注册所有事件监听器
   */
  private registerEventListeners() {
    if (!this.socket) return;

    // 聊天室事件
    this.socket.on("room_joined", data => this.emit("room_joined", data));
    this.socket.on("room_left", data => this.emit("room_left", data));
    this.socket.on("user_joined", data => this.emit("user_joined", data));

    // 消息事件
    this.socket.on("new_message", data => this.emit("new_message", data));

    // 输入状态
    this.socket.on("user_typing", data => this.emit("user_typing", data));

    // 会话状态变更
    this.socket.on("room_status_changed", data => this.emit("room_status_changed", data));

    // 会话分配
    this.socket.on("room_assigned", data => this.emit("room_assigned", data));

    // 房间在线用户更新
    this.socket.on("room_online_users_update", data => this.emit("room_online_users_update", data));

    // 用户状态变化
    this.socket.on("user_status_change", data => this.emit("user_status_change", data));
  }

  /**
   * 断开连接
   */
  disconnect() {
    if (this.socket) {
      this.socket.disconnect();
      this.socket = null;
      console.log("🔌 WebSocket 已断开");
    }
  }

  /**
   * 加入聊天室
   * @param roomId 聊天室ID
   */
  joinRoom(roomId: number) {
    this.send("join_room", { room_id: roomId });
  }

  /**
   * 离开聊天室
   * @param roomId 聊天室ID
   */
  leaveRoom(roomId: number) {
    this.send("leave_room", { room_id: roomId });
  }

  /**
   * 发送消息
   * @param roomId 聊天室ID
   * @param content 消息内容
   * @param type 消息类型
   */
  sendMessage(roomId: number, content: string, type: MessageType = "text") {
    this.send("send_message", {
      room_id: roomId,
      content,
      type
    });
  }

  /**
   * 发送输入状态
   * @param roomId 聊天室ID
   * @param isTyping 是否正在输入
   */
  sendTyping(roomId: number, isTyping: boolean) {
    this.send("typing", {
      room_id: roomId,
      is_typing: isTyping
    });
  }

  /**
   * 发送数据到服务器
   * @param event 事件名称
   * @param data 数据
   */
  private send(event: string, data: any) {
    if (!this.socket || !this.socket.connected) {
      console.error("❌ WebSocket 未连接,无法发送数据");
      return;
    }

    this.socket.emit(event, data);
  }

  /**
   * 注册事件处理器
   * @param event 事件名称
   * @param handler 处理函数
   */
  on<K extends keyof SocketEvents>(event: K, handler: SocketEvents[K]) {
    if (!this.eventHandlers.has(event)) {
      this.eventHandlers.set(event, new Set());
    }
    this.eventHandlers.get(event)!.add(handler);
  }

  /**
   * 移除事件处理器
   * @param event 事件名称
   * @param handler 处理函数
   */
  off<K extends keyof SocketEvents>(event: K, handler: SocketEvents[K]) {
    const handlers = this.eventHandlers.get(event);
    if (handlers) {
      handlers.delete(handler);
    }
  }

  /**
   * 触发事件
   * @param event 事件名称
   * @param data 事件数据
   */
  private emit(event: string, data: any) {
    const handlers = this.eventHandlers.get(event);
    if (handlers) {
      handlers.forEach(handler => {
        try {
          handler(data);
        } catch (error) {
          console.error(`事件 ${event} 处理器执行错误:`, error);
        }
      });
    }
  }

  /**
   * 检查连接状态
   */
  isConnected(): boolean {
    return this.socket !== null && this.socket.connected;
  }

  /**
   * 获取原始 Socket 实例 (谨慎使用)
   */
  getSocket(): Socket | null {
    return this.socket;
  }
}

// 导出单例实例
export const customerServiceSocket = new CustomerServiceSocket();

// 默认导出
export default customerServiceSocket;
